package com.joker.demo.core.executor.smart;

import com.joker.demo.core.domain.dto.EnvironmentMonitorDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.lang.management.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * 环境监控工具类
 * 用于收集执行器的运行环境信息，包括系统、JVM、磁盘、网络等
 *
 * @author : feixiang.li
 * @since : 2025-01-27 10:30
 */
public class EnvironmentMonitor {

    private static final Logger log = LoggerFactory.getLogger(EnvironmentMonitor.class);

    /**
     * 收集环境监控数据
     *
     * @param registerKey 执行器注册键
     * @param appName 应用名称
     * @return 环境监控数据
     */
    public static EnvironmentMonitorDTO collectEnvironmentData(String registerKey, String appName) {
        EnvironmentMonitorDTO monitorData = new EnvironmentMonitorDTO();
        
        try {
            // 设置基本信息
            monitorData.setRegisterKey(registerKey);
            monitorData.setAppName(appName);
            monitorData.setTimestamp(System.currentTimeMillis());
            
            // 收集系统信息
            monitorData.setSystemInfo(collectSystemInfo());
            
            // 收集JVM信息
            monitorData.setJvmInfo(collectJvmInfo());
            
            // 收集磁盘信息
            monitorData.setDiskInfos(collectDiskInfo());
            
            // 收集网络信息
            monitorData.setNetworkInfo(collectNetworkInfo());
            
            // 收集进程信息
            monitorData.setProcessInfo(collectProcessInfo());
            
            log.debug("环境监控数据收集完成，执行器：{}", registerKey);
            
        } catch (Exception e) {
            log.error("收集环境监控数据失败，执行器：{}，错误：{}", registerKey, e.getMessage(), e);
        }
        
        return monitorData;
    }

    /**
     * 收集系统信息
     */
    private static EnvironmentMonitorDTO.SystemInfo collectSystemInfo() {
        EnvironmentMonitorDTO.SystemInfo systemInfo = new EnvironmentMonitorDTO.SystemInfo();
        
        try {
            // 操作系统信息
            systemInfo.setOsName(System.getProperty("os.name"));
            systemInfo.setOsVersion(System.getProperty("os.version"));
            systemInfo.setOsArch(System.getProperty("os.arch"));
            
            // CPU信息
            systemInfo.setCpuCores(Runtime.getRuntime().availableProcessors());
            systemInfo.setCpuUsagePercent(getCpuUsagePercent());
            
            // 内存信息
            long totalMemory = Runtime.getRuntime().totalMemory();
            long freeMemory = Runtime.getRuntime().freeMemory();
            long maxMemory = Runtime.getRuntime().maxMemory();
            
            // 系统内存信息（这里使用JVM内存作为近似值，实际应该使用系统API）
            systemInfo.setTotalMemoryMB(maxMemory / (1024 * 1024));
            systemInfo.setUsedMemoryMB((totalMemory - freeMemory) / (1024 * 1024));
            systemInfo.setFreeMemoryMB(freeMemory / (1024 * 1024));
            systemInfo.setSystemMemoryUsagePercent(((double) (totalMemory - freeMemory) / maxMemory) * 100);
            
            // 系统负载（这里使用JVM运行时间作为近似值）
            systemInfo.setSystemLoadAverage(ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage());
            systemInfo.setUptimeSeconds(ManagementFactory.getRuntimeMXBean().getUptime() / 1000);
            
        } catch (Exception e) {
            log.error("收集系统信息失败：{}", e.getMessage(), e);
        }
        
        return systemInfo;
    }

    /**
     * 收集JVM信息
     */
    private static EnvironmentMonitorDTO.JvmInfo collectJvmInfo() {
        EnvironmentMonitorDTO.JvmInfo jvmInfo = new EnvironmentMonitorDTO.JvmInfo();
        
        try {
            RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
            MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
            ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
            ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
            
            // JVM基本信息
            jvmInfo.setJvmVersion(System.getProperty("java.version"));
            jvmInfo.setJvmVendor(System.getProperty("java.vendor"));
            jvmInfo.setJvmName(System.getProperty("java.vm.name"));
            jvmInfo.setStartTime(runtimeMXBean.getStartTime());
            jvmInfo.setUptime(runtimeMXBean.getUptime());
            
            // 堆内存信息
            MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
            jvmInfo.setMaxHeapMemoryMB(heapMemoryUsage.getMax() / (1024 * 1024));
            jvmInfo.setUsedHeapMemoryMB(heapMemoryUsage.getUsed() / (1024 * 1024));
            jvmInfo.setFreeHeapMemoryMB((heapMemoryUsage.getMax() - heapMemoryUsage.getUsed()) / (1024 * 1024));
            jvmInfo.setHeapMemoryUsagePercent(((double) heapMemoryUsage.getUsed() / heapMemoryUsage.getMax()) * 100);
            
            // 非堆内存信息
            MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
            jvmInfo.setMaxNonHeapMemoryMB(nonHeapMemoryUsage.getMax() / (1024 * 1024));
            jvmInfo.setUsedNonHeapMemoryMB(nonHeapMemoryUsage.getUsed() / (1024 * 1024));
            jvmInfo.setNonHeapMemoryUsagePercent(nonHeapMemoryUsage.getMax() > 0 ? 
                    ((double) nonHeapMemoryUsage.getUsed() / nonHeapMemoryUsage.getMax()) * 100 : 0.0);
            
            // 线程信息
            jvmInfo.setThreadCount(threadMXBean.getThreadCount());
            jvmInfo.setDaemonThreadCount(threadMXBean.getDaemonThreadCount());
            jvmInfo.setPeakThreadCount(threadMXBean.getPeakThreadCount());
            
            // 类加载信息
            jvmInfo.setClassLoaderCount(classLoadingMXBean.getLoadedClassCount());
            jvmInfo.setLoadedClassCount((long) classLoadingMXBean.getLoadedClassCount());
            jvmInfo.setTotalLoadedClassCount(classLoadingMXBean.getTotalLoadedClassCount());
            jvmInfo.setUnloadedClassCount(classLoadingMXBean.getUnloadedClassCount());
            
            // GC信息
            jvmInfo.setGcInfos(collectGcInfo());
            
        } catch (Exception e) {
            log.error("收集JVM信息失败：{}", e.getMessage(), e);
        }
        
        return jvmInfo;
    }

    /**
     * 收集GC信息
     */
    private static List<EnvironmentMonitorDTO.GcInfo> collectGcInfo() {
        List<EnvironmentMonitorDTO.GcInfo> gcInfos = new ArrayList<>();
        
        try {
            List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
            
            for (GarbageCollectorMXBean gcBean : gcBeans) {
                EnvironmentMonitorDTO.GcInfo gcInfo = new EnvironmentMonitorDTO.GcInfo();
                gcInfo.setGcName(gcBean.getName());
                gcInfo.setGcType(gcBean.getObjectName().getKeyProperty("type"));
                gcInfo.setCollectionCount(gcBean.getCollectionCount());
                gcInfo.setCollectionTime(gcBean.getCollectionTime());
                
                if (gcBean.getCollectionCount() > 0) {
                    gcInfo.setAverageCollectionTime((double) gcBean.getCollectionTime() / gcBean.getCollectionCount());
                } else {
                    gcInfo.setAverageCollectionTime(0.0);
                }
                
                gcInfos.add(gcInfo);
            }
            
        } catch (Exception e) {
            log.error("收集GC信息失败：{}", e.getMessage(), e);
        }
        
        return gcInfos;
    }

    /**
     * 收集磁盘信息
     */
    private static List<EnvironmentMonitorDTO.DiskInfo> collectDiskInfo() {
        List<EnvironmentMonitorDTO.DiskInfo> diskInfos = new ArrayList<>();
        
        try {
            File[] roots = File.listRoots();
            
            for (File root : roots) {
                EnvironmentMonitorDTO.DiskInfo diskInfo = new EnvironmentMonitorDTO.DiskInfo();
                diskInfo.setDiskName(root.getName());
                diskInfo.setDiskPath(root.getAbsolutePath());
                diskInfo.setTotalSpaceMB(root.getTotalSpace() / (1024 * 1024));
                diskInfo.setFreeSpaceMB(root.getFreeSpace() / (1024 * 1024));
                diskInfo.setUsedSpaceMB((root.getTotalSpace() - root.getFreeSpace()) / (1024 * 1024));
                diskInfo.setDiskUsagePercent(((double) (root.getTotalSpace() - root.getFreeSpace()) / root.getTotalSpace()) * 100);
                diskInfo.setFileSystemType("Unknown"); // Java无法直接获取文件系统类型
                
                diskInfos.add(diskInfo);
            }
            
        } catch (Exception e) {
            log.error("收集磁盘信息失败：{}", e.getMessage(), e);
        }
        
        return diskInfos;
    }

    /**
     * 收集网络信息
     */
    private static EnvironmentMonitorDTO.NetworkInfo collectNetworkInfo() {
        EnvironmentMonitorDTO.NetworkInfo networkInfo = new EnvironmentMonitorDTO.NetworkInfo();
        
        try {
            List<EnvironmentMonitorDTO.NetworkInterfaceInfo> networkInterfaces = new ArrayList<>();
            long totalBytesReceived = 0;
            long totalBytesSent = 0;
            long totalPacketsReceived = 0;
            long totalPacketsSent = 0;
            
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            
            while (interfaces.hasMoreElements()) {
                NetworkInterface networkInterface = interfaces.nextElement();
                
                EnvironmentMonitorDTO.NetworkInterfaceInfo interfaceInfo = new EnvironmentMonitorDTO.NetworkInterfaceInfo();
                interfaceInfo.setInterfaceName(networkInterface.getName());
                interfaceInfo.setDisplayName(networkInterface.getDisplayName());
                
                byte[] macAddress = networkInterface.getHardwareAddress();
                if (macAddress != null) {
                    StringBuilder mac = new StringBuilder();
                    for (int i = 0; i < macAddress.length; i++) {
                        mac.append(String.format("%02X%s", macAddress[i], (i < macAddress.length - 1) ? "-" : ""));
                    }
                    interfaceInfo.setMacAddress(mac.toString());
                }
                
                List<String> ipAddresses = new ArrayList<>();
                Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress address = addresses.nextElement();
                    ipAddresses.add(address.getHostAddress());
                }
                interfaceInfo.setIpAddresses(ipAddresses);
                
                interfaceInfo.setIsUp(networkInterface.isUp());
                interfaceInfo.setIsLoopback(networkInterface.isLoopback());
                
                // 网络统计信息（Java无法直接获取，这里设置为0）
                interfaceInfo.setBytesReceived(0L);
                interfaceInfo.setBytesSent(0L);
                interfaceInfo.setPacketsReceived(0L);
                interfaceInfo.setPacketsSent(0L);
                
                networkInterfaces.add(interfaceInfo);
                
                // 累计统计
                totalBytesReceived += interfaceInfo.getBytesReceived();
                totalBytesSent += interfaceInfo.getBytesSent();
                totalPacketsReceived += interfaceInfo.getPacketsReceived();
                totalPacketsSent += interfaceInfo.getPacketsSent();
            }
            
            networkInfo.setNetworkInterfaces(networkInterfaces);
            networkInfo.setTotalBytesReceived(totalBytesReceived);
            networkInfo.setTotalBytesSent(totalBytesSent);
            networkInfo.setTotalPacketsReceived(totalPacketsReceived);
            networkInfo.setTotalPacketsSent(totalPacketsSent);
            
        } catch (SocketException e) {
            log.error("收集网络信息失败：{}", e.getMessage(), e);
        }
        
        return networkInfo;
    }

    /**
     * 收集进程信息
     */
    private static EnvironmentMonitorDTO.ProcessInfo collectProcessInfo() {
        EnvironmentMonitorDTO.ProcessInfo processInfo = new EnvironmentMonitorDTO.ProcessInfo();
        
        try {
            RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
            OperatingSystemMXBean osMXBean = ManagementFactory.getOperatingSystemMXBean();
            ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
            
            // 进程基本信息
            processInfo.setPid(Long.parseLong(runtimeMXBean.getName().split("@")[0]));
            processInfo.setProcessName(System.getProperty("java.class.path"));
            
            // 进程CPU使用率（Java无法直接获取，这里设置为0）
            processInfo.setProcessCpuUsagePercent(0.0);
            
            // 进程内存使用
            MemoryUsage heapMemoryUsage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
            processInfo.setProcessMemoryUsageMB(heapMemoryUsage.getUsed() / (1024 * 1024));
            
            // 进程线程数
            processInfo.setProcessThreadCount(threadMXBean.getThreadCount());
            
            // 进程打开文件数（Java无法直接获取，这里设置为0）
            processInfo.setOpenFileCount(0L);
            
            // 进程优先级（Java无法直接获取，这里设置为0）
            processInfo.setPriority(0);
            
        } catch (Exception e) {
            log.error("收集进程信息失败：{}", e.getMessage(), e);
        }
        
        return processInfo;
    }

    /**
     * 获取CPU使用率
     * 注意：Java无法直接获取CPU使用率，这里返回一个近似值
     */
    private static Double getCpuUsagePercent() {
        try {
            OperatingSystemMXBean osMXBean = ManagementFactory.getOperatingSystemMXBean();
            // 使用系统负载平均值作为CPU使用率的近似值
            double loadAverage = osMXBean.getSystemLoadAverage();
            if (loadAverage >= 0) {
                int cpuCores = Runtime.getRuntime().availableProcessors();
                return Math.min(loadAverage / cpuCores * 100, 100.0);
            }
        } catch (Exception e) {
            log.debug("无法获取CPU使用率：{}", e.getMessage());
        }
        return 0.0;
    }
}
